package cn.wjh.business.service.impl;

import cn.wjh.business.domain.vo.MailVo;
import cn.wjh.business.domain.vo.RegisterVo;
import cn.wjh.business.service.ILoginService;
import cn.wjh.business.service.IMailService;
import cn.wjh.business.service.IMyCenterService;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.enums.UserStatus;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.ip.IpUtils;
import com.ruoyi.framework.manager.AsyncManager;
import com.ruoyi.framework.manager.factory.AsyncFactory;
import com.ruoyi.framework.web.service.SysPermissionService;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.mapper.SysUserMapper;
import com.ruoyi.system.service.ISysUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomUtils;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;

@Service
@Slf4j
public class LoginServiceImpl implements ILoginService {
	@Resource
	private IMailService mailService;

	@Resource
	private ISysUserService userService;

	@Resource
	private SysPermissionService permissionService;
	@Resource
	private RedisCache redisCache;

	@Resource
	private TokenService tokenService;

	@Resource
	private SysUserMapper userMapper;

	@Resource
	private IMyCenterService myCenterService;


	@Override
	public String mailLogin(MailVo mailVo) {
		if (!mailService.verifyCode(mailVo)) throw new ServiceException("邮箱验证码错误!", 400);
		/*获取用户信息*/
		SysUser user = userService.selectUserByEmail(mailVo.getEmail());

		if (StringUtils.isNull(user)) throw new ServiceException("用户不存在!");
		/*身份集合*/
		Set<String> postsSet = myCenterService.getPostsSet(user.getUserId());
		List<Long> postIds = myCenterService.getPostIds(user.getUserId());
		user.setPosts(postsSet);
		user.setPostIds(postIds);

		LoginUser loginUser = (LoginUser) validateUser(user);//检验用户
		recordLoginInfo(user.getUserId());//记录用户登录

		String code_key = mailVo.getTitle().concat(":" + mailVo.getEmail()).concat(":code");//邮箱验证码存储key title:to:code
		redisCache.deleteObject(code_key);//删除验证码


		AsyncManager.me().execute(AsyncFactory.recordLogininfor(user.getUserName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));


		//生成令牌
		return tokenService.createToken(loginUser);
	}

	/**
	 * 邮箱注册并登录
	 *
	 * @param registerVo
	 * @return
	 */
	@Override
	public String mailRegister(RegisterVo registerVo) {
		if (!mailService.verifyCode(registerVo)) throw new ServiceException("邮箱验证码错误!", 400);
		SysUser user = generateUser(registerVo);//生成用户
		if (StringUtils.isNull(user)) throw new ServiceException("注册失败!请重试!");

		/*身份集合*/
		Set<String> postsSet = myCenterService.getPostsSet(user.getUserId());
		user.setPosts(postsSet);

		LoginUser loginUser = (LoginUser) createLoginUser(user);//创建登录用户
		recordLoginInfo(user.getUserId());//记录用户登录

		String code_key = registerVo.getTitle().concat(":" + registerVo.getEmail()).concat(":code");//邮箱验证码存储key title:to:code
		redisCache.deleteObject(code_key);//删除验证码

		AsyncManager.me().execute(AsyncFactory.recordLogininfor(user.getUserName(), Constants.REGISTER, MessageUtils.message("user.register.success")));

		//生成令牌
		return tokenService.createToken(loginUser);
	}

	/**
	 * 生成用户 6-10位用户名
	 *
	 * @return
	 */
	private SysUser generateUser(RegisterVo registerVo) {
		long randomLong = RandomUtils.nextLong((long) Math.pow(10, 6), (long) Math.pow(10, 10));
		try {
			String username = String.valueOf(randomLong);
			SysUser user = new SysUser();
			user.setUserName(username);//用户名
			user.setNickName(registerVo.getNickname());//昵称
			user.setPassword(SecurityUtils.encryptPassword(registerVo.getPassword()));//密码
			user.setEmail(registerVo.getEmail());//邮箱
			user.setRoleIds(Collections.singletonList(2L));//默认普通角色
			user.setPostIds(Collections.singletonList(3L));//默认观众
			userService.insertUser(user);
			return userService.selectUserByUserName(username);//查找出完整的用户
		} catch (DuplicateKeyException e) {
			generateUser(registerVo);
			return null;
		}
	}

	/*检验用户*/
	private UserDetails validateUser(SysUser user) {
		verifyLoginUser(user, user.getUserName());
		return createLoginUser(user);
	}

	/*创建登录用户信息*/
	private UserDetails createLoginUser(SysUser user) {
		return new LoginUser(user.getUserId(), user.getDeptId(), user, permissionService.getMenuPermission(user), user.getPosts(), user.getPostIds());
	}

	private static void verifyLoginUser(SysUser user, String username) {
		if (StringUtils.isNull(user)) {
			log.info("登录用户：{} 不存在.", username);
			throw new ServiceException(MessageUtils.message("user.not.exists"));
		} else if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) {
			log.info("登录用户：{} 已被删除.", username);
			throw new ServiceException(MessageUtils.message("user.password.delete"));
		} else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
			log.info("登录用户：{} 已被停用.", username);
			throw new ServiceException(MessageUtils.message("user.blocked"));
		}
	}

	/**
	 * 记录登录信息
	 *
	 * @param userId
	 */
	private void recordLoginInfo(Long userId) {
		SysUser sysUser = new SysUser();
		sysUser.setUserId(userId);
		sysUser.setLoginIp(IpUtils.getIpAddr());
		sysUser.setLoginDate(DateUtils.getNowDate());
		userService.updateUserProfile(sysUser);
	}


}
